package com.googlecode.gwtbb.client.only.widget.display.forum;

import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.*;
import com.googlecode.gwtbb.client.only.ClientOnlyMessages;
import com.googlecode.gwtbb.client.only.GwtbbCmess;
import com.googlecode.gwtbb.client.only.glue.PathUtils;
import com.googlecode.gwtbb.client.only.glue.TokenOwner;
import com.googlecode.gwtbb.client.only.glue.events.forum.PostEventListener;
import com.googlecode.gwtbb.client.only.remote.ClientSession;
import com.googlecode.gwtbb.client.only.remote.NiceCallback;
import com.googlecode.gwtbb.client.only.remote.forum.ForumServiceProxy;
import com.googlecode.gwtbb.client.only.widget.SessionWidget;
import com.googlecode.gwtbb.client.only.widget.basic.ModuleHeader;
import com.googlecode.gwtbb.client.only.widget.display.user.UserLink;
import com.googlecode.gwtbb.client.only.widget.form.CompleteProcessListener;
import com.googlecode.gwtbb.client.only.widget.form.LoginProtectedLink;
import com.googlecode.gwtbb.client.only.widget.form.ProcessEvent;
import com.googlecode.gwtbb.client.only.widget.form.forum.CreatePostForm;
import com.googlecode.gwtbb.client.shared.entity.forum.Forum;
import com.googlecode.gwtbb.client.shared.entity.forum.Post;
import com.googlecode.gwtbb.client.shared.entity.user.User;
import com.googlecode.gwtbb.client.shared.remote.forum.CreatePostEvent;
import com.googlecode.gwtbb.client.shared.remote.forum.ForumPost;
import com.googlecode.gwtbb.client.shared.remote.forum.ForumPosts;
import com.googlecode.gwtbb.client.shared.util.StringUtils;

import java.util.List;

/**
 * @author Abraham Grief
 * @version $Id$
 * @since Jun 15, 2008
 */
public class ForumDetail extends SessionWidget implements TokenOwner, PostEventListener, CompleteProcessListener {
	protected static final ClientOnlyMessages c = GwtbbCmess.instance();
	private SimplePanel panel;
	private FlexTable threadTable;
	// todo take user to post detail after post is created
	private CreatePostForm createPostForm;
	private Label forumLabel;
	private Long forumId;

	public ForumDetail(ClientSession session) {
		super(session);

		VerticalPanel mainPanel = new VerticalPanel();
		initWidget(mainPanel);
		mainPanel.setWidth("100%");

		ModuleHeader moduleHeader = new ModuleHeader();
		mainPanel.add(moduleHeader);

		HorizontalPanel header = new HorizontalPanel();
		moduleHeader.setHeaderLeft(header);
		header.setStylePrimaryName("gwtbb-header");
		header.add(new ForumsLink());
		header.add(new HTML(c.logicalPathSeparator()));

		forumLabel = new Label();
		header.add(forumLabel);

		HorizontalPanel newPostPanel = new HorizontalPanel();
		moduleHeader.setHeaderRight(newPostPanel);
		newPostPanel.add(new LoginProtectedLink(getSession(), c.createThreadLink()) {
			public void ifLoggedIn() {
				createPostForm.setForumId(forumId);
				createPostForm.reset();
				panel.setWidget(createPostForm);
			}
		});

		panel = new SimplePanel();
		mainPanel.add(panel);
		panel.setWidth("100%");

		resetThreadTable();

		createPostForm = new CreatePostForm(session);
		createPostForm.getCancelButton().addClickListener(new ClickListener() {
			public void onClick(Widget sender) {
				panel.setWidget(threadTable);
			}
		});
		createPostForm.getCompleteProcessListenerCollection().addCompleteProcessListener(this);
	}

	private void resetThreadTable() {
		threadTable = new FlexTable();
		panel.setWidget(threadTable);
		threadTable.setWidth("100%");
		threadTable.setStylePrimaryName("gwtbb-spreadsheet");
	}

	public void onCreate(CreatePostEvent createPostEvent) {
		User sessionUser = getSession().getUser();
		if (sessionUser != null) {
			Post post = createPostEvent.getPost();
			if (post.getUserId().equals(sessionUser.getId())) {
				History.newItem(ThreadLink.buildTarget(createPostEvent.getThread(), createPostEvent.getForum()));
			}
		}
	}

	public void onProcessCompletion(ProcessEvent processEvent) {
		panel.setWidget(threadTable);
	}

	public boolean owns(String token) {
		return StringUtils.isNotEmpty(token);
	}

	public void serve(String token) {
		token = PathUtils.getTokenStart(token);
		resetThreadTable();
		final FlexTable.FlexCellFormatter fcf = threadTable.getFlexCellFormatter();
		threadTable.setWidget(0, 0, new Label(c.fieldHeaderSubject()));
		threadTable.setWidget(0, 1, new Label(c.fieldHeaderNumReplies()));
		threadTable.setWidget(0, 2, new Label(c.fieldHeaderThreadStarter()));
		threadTable.setWidget(0, 3, new Label(c.fieldHeaderLastPost()));
		formatRow(fcf, 0);
		displaySingleCell(fcf, c.loading());

		try {
			forumId = Long.valueOf(token);
			ForumServiceProxy.instance().getForumThreads(forumId, new NiceCallback<ForumPosts>() {
				public void handle(ForumPosts forumPosts) {
					Forum forum = forumPosts.getForum();

					if (forum != null) {
						forumLabel.setText(forum.getName());
						List<Post> threads = forumPosts.getPosts();
						if (threads != null && !threads.isEmpty()) {
							fcf.setColSpan(1, 0, 1);
							int row = 1;
							for (Post thread : threads) {
								threadTable.setWidget(row, 0, new ThreadLink(new ForumPost(forum, thread)));
								Post.Info threadInfo = thread.getInfo();
								if (threadInfo != null) {
									threadTable.setWidget(row, 1, new HTML(String.valueOf(threadInfo.getNumPostsInThread() - 1)));
									threadTable.setWidget(row, 2, new UserLink(threadInfo.getUser()));
									threadTable.setWidget(row, 3, new PostSummary(thread));
								} else {
									threadTable.setWidget(row, 1, new HTML());
									threadTable.setWidget(row, 2, new HTML());
									threadTable.setWidget(row, 3, new HTML());
								}
								formatRow(fcf, row++);
							}
						} else {
							displaySingleCell(fcf, c.noPosts());
						}
					} else {
						displaySingleCell(fcf, c.invalidForum());
					}
				}
			});
		} catch (NumberFormatException e) {
			resetThreadTable();
			displaySingleCell(fcf, c.invalidToken());
		}
	}

	private void displaySingleCell(FlexTable.FlexCellFormatter fcf, String errorMsg) {
		threadTable.setWidget(1, 0, new Label(errorMsg));
		fcf.setColSpan(1, 0, 4);
		fcf.setStylePrimaryName(1, 0, "gwtbb-spreadsheet-cell");
	}

	private void formatRow(FlexTable.FlexCellFormatter fcf, int row) {
		fcf.setStylePrimaryName(row, 0, "gwtbb-spreadsheet-cell");
		fcf.setStylePrimaryName(row, 1, "gwtbb-spreadsheet-cell");
		fcf.setStylePrimaryName(row, 2, "gwtbb-spreadsheet-cell");
		fcf.setStylePrimaryName(row, 3, "gwtbb-spreadsheet-cell");
	}
}
